package com.mjk.common.util;

import com.google.common.collect.Maps;
import com.mjk.common.tools.logger.BizLogger;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.PropertyUtilsBean;
import org.springframework.util.ObjectUtils;

import java.beans.PropertyDescriptor;
import java.util.Map;

public class DynamicBeanUtils {

    private DynamicBeanUtils(){}

	public static Object getTarget(Object dest, Map<String, Object> addProperties) {
        // get property map
        PropertyUtilsBean propertyUtilsBean = new PropertyUtilsBean();
        PropertyDescriptor[] descriptors = propertyUtilsBean.getPropertyDescriptors(dest);
        Map<String, Class> propertyMap = Maps.newHashMap();
        for (PropertyDescriptor d : descriptors) {
            if (!"class".equalsIgnoreCase(d.getName())) {
                propertyMap.put(d.getName(), d.getPropertyType());
            }
        }
        // add extra properties
        for (Map.Entry<String, Object> entry : addProperties.entrySet()) {
            if(!propertyMap.containsKey(entry.getKey())) {
                propertyMap.put(entry.getKey(), ObjectUtils.isEmpty(entry.getValue()) ? String.class : entry.getValue().getClass());
            }else{
                Object obj = ConvertUtils.convert(entry.getValue(), propertyMap.get(entry.getKey()));
                if(null != obj){
                    addProperties.put(entry.getKey(),obj);
                }else {
                    addProperties.put(entry.getKey(),entry.getValue());
                }
            }
        }
        //        addProperties.forEach((k, v) -> propertyMap.put(k, v.getClass()));
        // new dynamic bean
        DynamicBean dynamicBean = new DynamicBean(dest.getClass(), propertyMap);
        // add old value
        for (Map.Entry<String, Class> entry : propertyMap.entrySet()) {
            try {
                // filter extra properties
                if (!addProperties.containsKey(entry.getKey())) {
                    dynamicBean.setValue(entry.getKey(), propertyUtilsBean.getNestedProperty(dest, entry.getKey()));
                }
            } catch (Exception e) {
                BizLogger.error(e);
            }
        }
        // add extra value
        for (Map.Entry<String, Object> entry : addProperties.entrySet()) {
            try {
                dynamicBean.setValue(entry.getKey(), entry.getValue());
            } catch (Exception e) {
                BizLogger.error(e);
            }
        }
        return dynamicBean.getTarget();
    }

    /**
     * 获取动态类里面的值
     *
     * @param bean
     * @param key
     * @return
     */
    public Object getTargetValue(DynamicBean bean, String key) {
        return bean.getValue(key);
    }
}
